package com.fivestar.finance.library.widget.slidedatetimepicker;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.NumberPicker;
import android.widget.TextView;
import android.widget.TimePicker;

import com.fivestar.finance.library.R;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <p>The {@code DialogFragment} that contains the {@link SlidingTabLayout}
 * and {@link CustomViewPager}.</p>
 * <p>
 * <p>The {@code CustomViewPager} contains the  {@link TimeFragment}.</p>
 * <p>
 * <p>This {@code DialogFragment} is managed by {@link SlideTimePicker}.</p>
 *
 * @author jjobes
 */
public class SlideTimeDialogFragment extends DialogFragment implements
        TimeFragment.TimeChangedListener {
    public static final String TAG_SLIDE_TIME_DIALOG_FRAGMENT = "tagSlideTimeDialogFragment";

    private static SlideTimeListener mListener;

    private Context mContext;

    private TextView timeTitle;
    private TimePicker mTimePicker;
    private Button mOkButton;
    private Button mCancelButton;

    private Date initialTime;
    private boolean mIsClientSpecified24HourTime;
    private boolean mIs24HourTime;
    private int interval;


    private Calendar mCalendar;

    public SlideTimeDialogFragment() {
        // Required empty public constructor
    }

    /**
     * <p>Return a new instance of {@code SlideDateTimeDialogFragment} with its bundle
     * filled with the incoming arguments.</p>
     * <p>
     * <p>Called by {@link SlideDateTimePicker#show()}.</p>
     *
     * @param listener
     * @param isClientSpecified24HourTime
     * @param is24HourTime
     * @return
     */
    public static SlideTimeDialogFragment newInstance(SlideTimeListener listener,
                                                      Date initialTime,
                                                      boolean isClientSpecified24HourTime,
                                                      boolean is24HourTime, int interval) {
        mListener = listener;

        // Create a new instance of SlideDateTimeDialogFragment
        SlideTimeDialogFragment dialogFragment = new SlideTimeDialogFragment();

        // Store the arguments and attach the bundle to the fragment
        Bundle bundle = new Bundle();
        bundle.putSerializable("initialTime", initialTime);
        bundle.putBoolean("isClientSpecified24HourTime", isClientSpecified24HourTime);
        bundle.putBoolean("is24HourTime", is24HourTime);
        bundle.putInt("interval", interval);
        dialogFragment.setArguments(bundle);

        // Return the fragment with its bundle
        return dialogFragment;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        mContext = activity;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setRetainInstance(true);
        unpackBundle();
        mCalendar = Calendar.getInstance();
        mCalendar.setTime(initialTime);
        setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog_NoActionBar);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide_time_picker, container);

        setupViews(view);
        initButtons();

        mTimePicker.setDescendantFocusability(DatePicker.FOCUS_BLOCK_DESCENDANTS);
        mTimePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {

            @Override
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
                SlideTimeDialogFragment.this.onTimeChanged(hourOfDay, minute % (60 / interval) * interval);
            }
        });

        // If the client specifies a 24-hour time format, set it on
        // the TimePicker.
        if (mIsClientSpecified24HourTime) {
            mTimePicker.setIs24HourView(mIs24HourTime);
        } else {
            // If the client does not specify a 24-hour time format, use the
            // device default.
            mTimePicker.setIs24HourView(DateFormat.is24HourFormat(
                    getTargetFragment().getActivity()));
        }


        mTimePicker.setCurrentHour(mCalendar.get(Calendar.HOUR_OF_DAY));

        if (interval >= 1) {
            mTimePicker.setCurrentMinute(0);
        } else {
            mTimePicker.setCurrentMinute(mCalendar.get(Calendar.MINUTE));
        }

        // Fix for the bug where a TimePicker's onTimeChanged() is not called when
        // the user toggles the AM/PM button. Only applies to 4.0.0 and 4.0.3.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&
                Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
            fixTimePickerBug18982();
        }
        if (interval >= 1)
            setTimePickerInterval(interval);
        return view;
    }

    /**
     * 设置分钟间隔
     *
     * @param
     * @see [类、类#方法、类#成员]
     */
    private void setTimePickerInterval(int TIME_PICKER_INTERVAL) {
        try {
            Class<?> classForid = Class.forName("com.android.internal.R$id");
            Field minuteField = classForid.getField("minute");
            NumberPicker minutePicker = (NumberPicker) mTimePicker.findViewById(minuteField.getInt(null));

            minutePicker.setMinValue(0);
            minutePicker.setMaxValue(3);
            List<String> displayedValues = new ArrayList<String>();
            for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
                displayedValues.add(String.format("%02d", i));
            }
            for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
                displayedValues.add(String.format("%02d", i));
            }
            minutePicker.setDisplayedValues(displayedValues.toArray(new String[0]));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroyView() {
        // Workaround for a bug in the compatibility library where calling
        // setRetainInstance(true) does not retain the instance across
        // orientation changes.
        if (getDialog() != null && getRetainInstance()) {
            getDialog().setDismissMessage(null);
        }

        super.onDestroyView();
    }

    private void unpackBundle() {
        Bundle args = getArguments();
        initialTime = (Date) args.getSerializable("initialTime");
        mIsClientSpecified24HourTime = args.getBoolean("isClientSpecified24HourTime");
        mIs24HourTime = args.getBoolean("is24HourTime");

        interval = args.getInt("interval");
    }

    private void setupViews(View v) {
        timeTitle = (TextView) v.findViewById(R.id.tv_title_time);
        mTimePicker = (TimePicker) v.findViewById(R.id.timePicker);

        mOkButton = (Button) v.findViewById(R.id.okButton);
        mCancelButton = (Button) v.findViewById(R.id.cancelButton);
    }

    private void initButtons() {
        mOkButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mListener == null) {
                    throw new NullPointerException(
                            "Listener no longer exists for mOkButton");
                }
                if (mIs24HourTime) {
                    mListener.onTimeSet(mCalendar.get(Calendar.HOUR_OF_DAY), mCalendar.get(Calendar.MINUTE));
                } else {
                    mListener.onTimeSet(mCalendar.get(Calendar.HOUR), mCalendar.get(Calendar.MINUTE));
                }
                dismiss();
            }
        });

        mCancelButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mListener == null) {
                    throw new NullPointerException(
                            "Listener no longer exists for mCancelButton");
                }
                mListener.onTimeCancel();
                dismiss();
            }
        });
    }


    /**
     * <p>The callback used by the TimePicker to update {@code mCalendar} as
     * the user changes the time. Each time this is called, we also update
     * the text on the time tab to reflect the time the user has currenly
     * selected.</p>
     * <p>
     * <p>Implements the {@link TimeFragment.TimeChangedListener}
     * interface.</p>
     */
    @Override
    public void onTimeChanged(int hour, int minute) {
        if (mIs24HourTime) {
            mCalendar.set(Calendar.HOUR_OF_DAY, hour);
        } else {
            mCalendar.set(Calendar.HOUR, hour);
        }
        mCalendar.set(Calendar.MINUTE, minute);

        timeTitle.setText(hour + ":" + (minute == 0 ? "00" : minute));
    }


    /**
     * <p>Called when the user clicks outside the dialog or presses the <b>Back</b>
     * button.</p>
     * <p>
     * <p><b>Note:</b> Actual <b>Cancel</b> button clicks are handled by {@code mCancelButton}'s
     * event handler.</p>
     */
    @Override
    public void onCancel(DialogInterface dialog) {
        super.onCancel(dialog);

        if (mListener == null) {
            throw new NullPointerException(
                    "Listener no longer exists in onCancel()");
        }
        mListener.onTimeCancel();
    }

    /**
     * Workaround for bug in Android TimePicker where the onTimeChanged() callback
     * is not invoked when the user toggles between AM/PM. But we need to be able
     * to detect this in order to dynamically update the tab title properly when
     * the user toggles between AM/PM.
     * <p>
     * Registered as Issue 18982:
     * <p>
     * https://code.google.com/p/android/issues/detail?id=18982
     */
    private void fixTimePickerBug18982() {
        View amPmView = ((ViewGroup) mTimePicker.getChildAt(0)).getChildAt(3);

        if (amPmView instanceof NumberPicker) {
            ((NumberPicker) amPmView).setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {

                @Override
                public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                    if (picker.getValue() == 1)  // PM
                    {
                        if (mTimePicker.getCurrentHour() < 12)
                            mTimePicker.setCurrentHour(mTimePicker.getCurrentHour() + 12);
                    } else  // AM
                    {
                        if (mTimePicker.getCurrentHour() >= 12)
                            mTimePicker.setCurrentHour(mTimePicker.getCurrentHour() - 12);
                    }

                    onTimeChanged(
                            mTimePicker.getCurrentHour(),
                            mTimePicker.getCurrentMinute());
                }
            });
        }
    }

}
